﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using RW.Data.Graph;
using RW.Data.Objects;
using QuickGraph.Algorithms;

namespace RW.Data
{
    public class Query1
    {
        public List<string> Program { get; set; }
        public Dictionary<string, bool> Conditions { get; set; }

        public int Cost { get; set; }

        private MultiGraph graph;

        public Query1(MultiGraph multiGraph)
        {
            Cost = int.MaxValue;
            Program = new List<string>();
            Conditions = new Dictionary<string, bool>();
            graph = multiGraph;
        }

        public string Compute(bool isAlways)
        {
            try
            {
                List<State> startingVertices = graph.Vertices.Where(v => v.SatisfiesConditions(Conditions)).ToList();
                int counter = 0;
                int cost = 0;
                int maxPathValue = 0;
                int minPathValue = int.MaxValue;
                foreach (var vertex in startingVertices)
                {
                    int currentCost = GoingDeep(vertex, counter, cost, isAlways);
                    if (isAlways)
                    {
                        if (currentCost > maxPathValue)
                            maxPathValue = currentCost;
                    }
                    else
                    {
                        if (currentCost < minPathValue)
                            minPathValue = currentCost;
                    }
                }
                //if (maxPathValue > Cost || minPathValue > Cost)
                //    return "false";
                //return "true";
                return isAlways ? (maxPathValue <= Cost).ToString() : (minPathValue <= Cost).ToString();
            }
            catch (Exception e)
            {
                if (e.GetType() == typeof(BrokenPathException))
                    return "false";
                return "error";
            }
        }

        public int GoingDeep(State vertex, int counter, int cost, bool isAlways)
        {
            if (counter == Program.Count())
                return cost;
            var edges = graph.OutEdges(vertex).Where(e => e.ActionName.Equals(Program[counter]));
            if (edges.Count() == 0 && isAlways)
                throw new BrokenPathException("Ścieżka przerwana co w przypadku Q1-always jest niedopuszczalne");
            int maxCost = cost;
            int minCost = int.MaxValue;
            foreach (var edge in edges)
            {
                int currentCost = GoingDeep(edge.Target, counter + 1, cost + edge.ActionCost, isAlways);
                if (isAlways)
                {
                    if (currentCost > maxCost)
                        maxCost = currentCost;
                }
                else
                {
                    if (currentCost < minCost)
                        minCost = currentCost;
                }
            }
            return isAlways ? maxCost : minCost;
        }
    }

    public class BrokenPathException : Exception
    {
        public BrokenPathException(string msg) : base(msg) { }
    }
}
